﻿//========================================================= 
/**@file H002MagCmdDriver.h
 * @brief H002磁条指令
 * 
 * @date 2016-10-03   11:43:07
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_H002MAGCMDDRIVER_H_
#define _LIBZHOUYB_H002MAGCMDDRIVER_H_
//--------------------------------------------------------- 
#include "../CommonCmdDriver.h"

#include "../../magnetic/H002MagDevAdapter.h"
using zhou_yb::application::magnetic::H002MagDevAdapter;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
/// H002磁条命令
class H002MagCmdDriver : 
    public CommonCmdDriver, 
    public BaseDevAdapterBehavior<IInteractiveTrans>
{
protected:
    H002MagDevAdapter _magAdapter;
    // 解析磁条数据
    bool _ParseMAG(IStringArguments& arg, ByteBuilder* pTr1, ByteBuilder* pTr2, ByteBuilder* pTr3)
    {
        ByteBuilder buff(128);
        string sBuff = arg["TrBuff"].To<string>();
        ByteConvert::FromAscii(ByteArray(sBuff.c_str(), sBuff.length()), buff);

        MagneticDevAdapter::MagneticMode mode = MagneticDevAdapter::UnpackRecvCmd(buff, pTr1, pTr2, pTr3);
        if(mode == MagneticDevAdapter::UnKnownMode)
        {
            _logErr(DeviceError::RecvFormatErr, "磁条数据格式不正确");
            return false;
        }
        return true;
    }
    // 截取卡号
    bool _TrimCardNumber(const ByteArray& tr2, ByteBuilder& cardNumber)
    {
        size_t index = StringConvert::IndexOf(tr2, '=');
        if(index == SIZE_EOF)
            index = StringConvert::IndexOf(tr2, '\'');
        cardNumber = tr2.SubArray(0, index);
        return true;
    }
public:
    H002MagCmdDriver() : CommonCmdDriver()
    {
        _errGetter.Add(_magAdapter);
        _logSetter.select(_magAdapter);

        _RegisteCMD(H002MagCmdDriver, WaitForMagCard);
        _RegisteCMD(H002MagCmdDriver, WaitForEncryptMagCard);
        _RegisteCMD(H002MagCmdDriver, MagReset);
        _RegisteCMD(H002MagCmdDriver, MagRead);
        _RegisteCMD(H002MagCmdDriver, MagEncryptRead);
        _RegisteCMD(H002MagCmdDriver, ParseMAG);
        _RegisteCMD(H002MagCmdDriver, ParseEncryptMAG);
        _RegisteCMD(H002MagCmdDriver, IsMagPresent);
        _RegisteCMD(H002MagCmdDriver, IsPollingMode);
        _RegisteExceptCMD(H002MagCmdDriver);

        _RegisteCancelCMD(H002MagCmdDriver);
        _RegisteAdapterCMD(H002MagCmdDriver);
    }
    LC_CMD_CANCEL(_magAdapter);
    LC_CMD_ADAPTER_INVOKE(IInteractiveTrans, _magAdapter);
    LC_CMD_EXCEPT()
    {
        EXCEPT_CMD(ParseMAG);
        EXCEPT_CMD(ParseEncryptMAG);
        return true;
    }
    /**
     * @brief 清除磁条状态
     * @date 2017-05-23 11:42
     */
    LC_CMD_METHOD(MagReset)
    {
        return _magAdapter.MagClear();
    }
    /**
     * @brief 等待读取磁条
     * @date 2016-10-26 21:43
     * 
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待的超时时间(ms)
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 轮询的超时时间(ms)
     * @param [in] IsAutoMAG : [default:true] 是否自动发送读磁条指令和清磁条状态指令(自动触发MagRead和MagReset) 
     *
     * @retval CardNumber : string 二磁道中的卡号
     * @retval Tr1 : string 一磁道数据
     * @retval Tr2 : string 二磁道数据
     * @retval Tr3 : string 三磁道数据
     */
    LC_CMD_METHOD(WaitForMagCard)
    {
        ByteBuilder tr1(128);
        ByteBuilder tr2(128);
        ByteBuilder tr3(128);

        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);
        bool isAutoMAG = arg["IsAutoMAG"].To<bool>(true);

        _magAdapter.SetWaitTimeout(timeoutMs);
        _magAdapter.SetOperatorInterval(intervalMs);

        if(isAutoMAG)
        {
            ASSERT_FuncErrInfo(_magAdapter.MagRead(), DeviceError::OperatorErr, "开始明文读磁条失败");
        }
        bool bOK = _magAdapter.WaitMagCard(&tr1, &tr2, &tr3);
        if(!bOK)
        {
            _logErr(_magAdapter);
            if(isAutoMAG)
            {
                _magAdapter.MagClear();
            }
            return false;
        }
        
        ByteBuilder cardNumber(20);
        _TrimCardNumber(tr2, cardNumber);
        rlt.Put("CardNumber", cardNumber.GetString());

        rlt.Put("Tr1", tr1.GetString());
        rlt.Put("Tr2", tr2.GetString());
        rlt.Put("Tr3", tr3.GetString());
        return true;
    }
    /**
     * @brief 等待读取加密磁条
     * @date 2016-10-26 21:47
     * 
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待的超时时间(ms)
     * @param [in] Interval : uint [default:DEV_OPERATOR_INTERVAL] 轮询的超时时间(ms)
     * @param [in] IsAutoMAG : [default:true] 是否自动发送读磁条指令和清磁条状态指令(自动触发MagRead和MagReset)
     *
     * @param [in] MkIndex : size_t 加密磁条的主密钥索引
     * @param [in] WkIndex : size_t 加密磁条的工作密钥索引
     * 
     * @retval Tr1 : hex 加密后的一磁道数据
     * @retval Tr2 : hex 加密后的二磁道数据
     * @retval Tr3 : hex 加密后的三磁道数据
     */
    LC_CMD_METHOD(WaitForEncryptMagCard)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        uint intervalMs = arg["Interval"].To<uint>(DEV_OPERATOR_INTERVAL);
        uint mkIndex = arg["MkIndex"].To<uint>();
        uint wkIndex = arg["WkIndex"].To<uint>();
        bool isAutoMAG = arg["IsAutoMAG"].To<bool>(true);

        _magAdapter.SetWaitTimeout(timeoutMs);
        _magAdapter.SetOperatorInterval(intervalMs);
        if(isAutoMAG)
        {
            ASSERT_FuncErrInfo(_magAdapter.MagEncryptRead(mkIndex, wkIndex), DeviceError::OperatorErr, "开始加密读磁条失败");
        }
        ByteBuilder tr1(128);
        ByteBuilder tr2(128);
        ByteBuilder tr3(128);

        bool bOK = _magAdapter.WaitEncryptMagCard(&tr1, &tr2, &tr3);
        if(!bOK)
        {
            if(isAutoMAG)
            {
                _magAdapter.MagClear();
            }
            _logErr(DeviceError::WaitTimeOutErr, "等待刷磁超时");
            return false;
        }
        
        rlt.Put("Tr1", tr1.GetString());
        rlt.Put("Tr2", tr2.GetString());
        rlt.Put("Tr3", tr3.GetString());
        return true;
    }
    /**
     * @brief 开始明文读取磁条
     * @date 2016-10-26 23:22
     */
    LC_CMD_METHOD(MagRead)
    {
        return _magAdapter.MagRead();
    }
    /**
     * @brief 开始密文读取磁条
     * @date 2016-10-26 23:22
     * 
     * @param [in] MkIndex : size_t 加密磁条的主密钥索引
     * @param [in] WkIndex : size_t 加密磁条的工作密钥索引
     */
    LC_CMD_METHOD(MagEncryptRead)
    {
        uint mkIndex = arg["MkIndex"].To<uint>();
        uint wkIndex = arg["WkIndex"].To<uint>();
        return _magAdapter.MagEncryptRead(mkIndex, wkIndex);
    }
    /**
     * @brief 解析 IsMagPresent 返回的磁条数据
     * @date 2016-10-26 23:07
     * 
     * @param [in] TrBuff : hex 读取到的磁条数据
     * 
     * @retval CardNumber : string 二磁道中截取出来的卡号
     * @retval Tr1 : string 一磁道数据 
     * @retval Tr2 : string 二磁道数据
     * @retval Tr3 : string 三磁道数据
     */
    LC_CMD_METHOD(ParseMAG)
    {
        ByteBuilder tr1(128);
        ByteBuilder tr2(128);
        ByteBuilder tr3(128);
        if(!_ParseMAG(arg, &tr1, &tr2, &tr3))
            return false;

        ByteBuilder cardNumber(8);
        _TrimCardNumber(tr2, cardNumber);
        rlt.Put("CardNumber", cardNumber.GetString());

        rlt.Put("Tr1", tr1.GetString());
        rlt.Put("Tr2", tr2.GetString());
        rlt.Put("Tr3", tr3.GetString());
        return true;
    }
    /**
     * @brief 解析 IsMagPresent 返回的密文磁条数据
     * @date 2016-10-26 23:08
     * 
     * @param [in] TrBuff : hex 读取到的磁条数据
     * 
     * @retval Tr1 : hex 一磁道数据
     * @retval Tr2 : hex 二磁道数据
     * @retval Tr3 : hex 三磁道数据
     */
    LC_CMD_METHOD(ParseEncryptMAG)
    {
        ByteBuilder tr1(128);
        ByteBuilder tr2(128);
        ByteBuilder tr3(128);
        if(!_ParseMAG(arg, &tr1, &tr2, &tr3))
            return false;

        ByteBuilder tmp(128);
        ByteConvert::Fold(tr1, tmp);
        rlt.Put("Tr1", tmp.GetString());

        tmp.Clear();
        ByteConvert::Fold(tr2, tmp);
        rlt.Put("Tr2", tmp.GetString());

        tmp.Clear();
        ByteConvert::Fold(tr3, tmp);
        rlt.Put("Tr3", tmp.GetString());
        return true;
    }
    /**
     * @brief 返回当前是否刷过磁条
     * @date 2016-10-26 23:08
     * 
     * @retval TrBuff : hex 读取到的磁条数据,空表示还未刷过磁条
     * @retval HasMAG : bool 是否刷过磁条
     */
    LC_CMD_METHOD(IsMagPresent)
    {
        ByteBuilder trBuff(256);
        DeviceError::ErrorCode err = H002MagDevAdapter::IsMagPresent(_pDev, trBuff);
        if(DeviceError::IsSuccess(err))
        {
            ByteBuilder tmp(32);
            ByteConvert::ToAscii(trBuff, tmp);
            rlt.Put("HasMAG", ArgConvert::ToString(true));
            rlt.Put("TrBuff", tmp.GetString());
            return true;
        }
        if(err == DeviceError::DevIsBusyErr)
        {
            rlt.Put("HasMAG", ArgConvert::ToString(false));
            return true;
        }

        _logErr(err, "PollMAG");
        return false;
    }
    /**
     * @brief 返回磁条设备是否为轮询方式
     * @date 2017-05-10 23:18
     * 
     * @retval IsPolling : bool 是否为轮询方式
     */
    LC_CMD_METHOD(IsPollingMode)
    {
        bool isPolling = false;
        if(!_magAdapter.IsPollingMode(isPolling))
            return false;
        rlt.Put("IsPolling", ArgConvert::ToString(isPolling));
        return true;
    }
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_H002MAGCMDDRIVER_H_
//========================================================= 